package _2_var

import (
	"fmt"
	"strconv"
	"unsafe"
)
// go 中的数据类型
func Type() {
	// 1. 基本数据类型
	// 整数类型  int, int8(-128~127), int16,int32, int64, uint64, uint, uint8, uint16, uint32, uint32, uint64, rune(等价～int32), byte(0~255)
	// 浮点类型 float32, float64 没有double类型用长度来区分
	// 字符类型 byte
	// 布尔类型 bool
	// 字符串类型 string

	var num = 28
	fmt.Printf("num3的类型是 %T \n", num)

	// num3占用的字节
	fmt.Println(unsafe.Sizeof(num))

	// byte 是0～255，使用最小范围
	var age byte =18
	fmt.Println("age =", age)

	//定义浮点类型的数据:可以使用十进制表示，也可以使用科学计数法表示，E/e表示
	var num1 float32 = 3.14
	fmt.Println(num1)
	var num2 float32 = -3.14
	fmt.Println(num2)
	var num3 float32 = 314E-2
	fmt.Println(num3)
	var num4 float32 = 314E+2
	fmt.Println(num4)
	var num5 float32 = 314e+2
	fmt.Println(num5)
	var num6 float64 = 314e+2
	fmt.Println(num6)

	//------->浮点数可能会有精度的损失，所以通常情况下，建议你使用: float64
	var num7 float32 = 256.000000916
	fmt.Println(num7)
	var num8 float64 = 256.000000916 // 推荐使用float64, 默认值也是flat64
	fmt.Println(num8)

	// -------->字符类型是ASCII码 0～255
	//定义字符类型的数据:
	var c1 byte = 'a'
	fmt.Println(c1) //97
	var c2 byte = '6'
	fmt.Println(c2) //54
	var c3 byte = '('
	fmt.Println(c3 + 20) //40
	//字符类型，本质上就是一个整数，也可以直接参与运算，输出字符的时候，会将对应的码值做一个输出
	//字母，数字，标点等字符，底层是按照ASCII进行存储。
	var c4 int = '中'
	fmt.Println(c4)
	//汉字字符，底层对应的是Unicode码值，ASCII码是Unicode码的前128位
	//对应的码值为20013，byte类型溢出，能存储的范围:可以用int
	//总结: Golang的字符对应的使用的是 Unicode码是字符集，UTF-8编码是底层方案
	var c5 byte = 'A'
	//想显示对应的字符，必须采用格式化输出
	fmt.Printf(" c5对应的具体的字符为: %c", c5)

	// --------> 转译字符
	fmt.Println("aaa\nbbbb")

	// --------->布尔类型 bool
	var flag bool = true
	fmt.Println("布尔类型bool", flag)

	var flag2 bool = 3 < 6
	fmt.Println("布尔类型 3 < 6", flag2)

	// ------------>字符串类型 string
	var str1 string = "字符串"
	fmt.Println("字符串str1", str1)
	// 如果字符串中不包含转译字符用双引号
	// 如果字符串中包含转移字符
	//当一个字符串过长的时候:注意: +保留在上一行的最后
	var str2 string = `abc\nb`
	var str3 = str2 + `&&&&&&&888888`
	fmt.Println("字符串str3", str3)

	// 2.派生数据类型
	// 指针
	// 数组
	// 结构图
	// 管道
	// 函数
	// 切片
	// 接口
	// map

}


// go中的变量和常量
func variable() {
	// 定义变量的方式
	var s string
	fmt.Println(s) // string 默认值空串
	var a, b int
	fmt.Println(a, b)
	fmt.Println("-----------------")

	// 使用 = 给变量赋值
	s = "hello world"
	fmt.Println(s)
	a, b = 1, 2
	fmt.Println(a, b)
	c, d := 3, "4"
	fmt.Println("定义并赋值多个变量c, d", c, d)

	// 使用 := 给变量赋值，可以不定义变量类型
	n := 3
	fmt.Println(n)

	// 一次声明多个变量
	var (
		m string = "hello world"
		x int    = 1
		z int    = 2
	)
	fmt.Println(m, x, z)

	// 定义常量
	const (
		i = ""
		j = 1
	)
	fmt.Println(i)
	fmt.Println(j)
	const PI = 3.1415
	const E float32 = 2.7182
	fmt.Println(PI)
	fmt.Println(E)

}


// 类型转换
func typeConverter() {

	// 进行关型转换:
	var n1 int = 100
	//var n2 float32 = n1 在这里自动转换不好使，比如显式转换
	fmt.Println(n1)
	// fmt . Println(n2)
	var n2 float32 = float32(n1)
	fmt.Println(n2)
	//注意: n1的类型其实还是int类型，只是将n1的值100转为了float32而己，n1还 是int的类型
	fmt.Printf("%T", n1) //Int

	// 将大类型转为小类型
	var n3 int64 = 8888888
	var n4 int8 = int8(n3)
	fmt.Println(n4)

	// 将小类型转为大类型
	var n5 int32 = 12
	var n6 int64 = int64(n5) + 30 // 会报错
	fmt.Println(n6)

	var n7 int64 = 12
	var n8 int8 = int8(n7) + 127
	//编译通过，但是结果可能会溢出
	//var n9 int8 = int8(n7) + 128 //编译报错
	fmt.Println(n8)

}

//基本转string
func stringConvert() {
	var n1 int = 19
	var n2 float32 = 4.78
	var n3 bool = false
	var n4 byte = 'a'
	var s1 string = fmt.Sprintf("%d", n1) // %d: 整数用十进制输出
	fmt.Printf(" s1对应大类型是: %T , s1 = %q \n", s1, s1) // %T:输出类型，%q: 内容用双引号""
	var s2 string = fmt.Sprintf("%f", n2) // %f: 有小数部分但无指数
	fmt.Printf("s2对应的类型是: %T , s2 = %q ", s2, s2)
	var s3 = fmt.Sprintf("%t", n3)  // %t: bool类型的值
	fmt.Println("n3的类型是:", s3)

	fmt.Printf("s3对应的类型是: %T , s3 = %q ", s3, s3)
	var s4 string = fmt.Sprintf("%c", n4)
	fmt.Printf(" s4对应的类型是: %T , s4 = %q , %c", s4, s4, n4) // %c:该值对应的unicode码值

	var coN1 int = 18
	var covs1 string = strconv.FormatInt(int64(coN1), 10) // //参数:第一个参数必须转为int64类型，第二个参数指定字面值的进制形式为十进制
	fmt.Printf("s1Xf IÉ##Æ: %T s1 %q In", covs1, covs1)
	var covn2 float64 = 4.29
	var covs2 string = strconv.FormatFloat(covn2, 'f', 9, 64)
	//第二个参数: 'f' (-ddd. dddd)
	//第三个参数: 9保留小数点后面9位第四个参数: 表示这个小数是float64类型
	fmt.Printf(" s2对应的类型是: %T，s2 = %q \n", covs2, covs2)
}

//string转基本类型
func convertString() {

	//string-->bool
	var s1 string = "true"
	var b bool
	//ParseBool这个函数的返回值有两个: (value bool, err error)
	//value就是我们得到的布尔类型的数据，err 出现的错误
	//我们只关注得到的布尔类型的数据，err可以用_直接忽略
	strconv.ParseBool(s1)
	fmt.Printf("b的类型是: %т,b=%v In", b, b)
	//string---» int64
	var s2 string = "19"
	var num1 int64
	num1, _ = strconv.ParseInt(s2, 10, 64)
	fmt.Printf("num1: %T , num1=%v n", num1, num1)
	//string-->float32/float64
	var s3 string = "3.14"
	var f1 float64
	f1, _ = strconv.ParseFloat(s3, 64)
	fmt.Printf("f1的类型是: %т,f1=%v In", f1, f1)
}

func importVar() {
	// 导入另外一个文件中的成员变量，变量名要定义大写开始
}


// 变量的作用域
func scope()  {

	calculateAdd := func(a, b float64) float64 {
		return a + b
	}
	result := calculateAdd(1.0, 2.0)
	fmt.Println(result)

	name := "小强"
	{
		person1Total := 20.1
		person1Weight := 30.0
		calculateAdd(person1Total, person1Weight)
	}
	{
		name := "小明"    // 这个是重新定义
		fmt.Println("name:", name)
		person2Total := 21.0
		person2Weight := 21.0
		calculateAdd(person2Total, person2Weight)
		fmt.Println("name>>>", name) // out put: 小强
		name = "小张" // 重新赋值

	}
	fmt.Println("name>>>", name) // out put: 小张
}


